-module(ehttp).

-export([
    start/1
    ,stop/1
]).


%%%===================================================================
%%% API functions
%%%===================================================================

start(ArgMap = #{ref := Ref, port := Port, routes := RestRoutes}) ->
    [Middles0, StaticPrefix, StaticDir, RawRoutes, SslCertFile, SslKeyFile] = get_options(ArgMap, [middles, static_prefix, static_dir, raw_routes, ssl_cert_file, ssl_key_file]),

    Middles = ehttp_util:fix_middle(Middles0),

    Routes = get_routes(StaticPrefix, StaticDir, RestRoutes, RawRoutes, Middles),

    Dispatch = cowboy_router:compile(Routes),

    case SslCertFile == undefined orelse SslKeyFile == undefined of
        true ->
            {ok, _} = cowboy:start_clear(Ref, [{port, Port}], #{env => #{dispatch => Dispatch}});
        false ->
            {ok, _} = cowboy:start_tls(Ref, [{port, Port}, {certfile, SslCertFile}, {keyfile, SslKeyFile}], #{env => #{dispatch => Dispatch}})
    end.

stop(Ref) ->
    cowboy:stop_listener(Ref).


%%%===================================================================
%%% Internal functions
%%%===================================================================

get_options(ArgMap, Opts) ->
    get_options(ArgMap, Opts, []).

get_options(_ArgMap, [], OptDatas) ->
    lists:reverse(OptDatas);
get_options(ArgMap, [Opt | Opts], OptDatas) ->
    Val = maps:get(Opt, ArgMap, undefined),
    get_options(ArgMap, Opts, [Val | OptDatas]).

get_routes(undefined, _StaticDir, RestRoutes, undefined, Middles) ->
    [
        {'_', [
            {'_',           ehttp_handler,  #{routes => RestRoutes, middles => Middles}}
        ]}
    ];
get_routes(undefined, _StaticDir, RestRoutes, RawRoutes, Middles) ->
    [
        {'_', RawRoutes ++ [
            {'_',           ehttp_handler,  #{routes => RestRoutes, middles => Middles}}
        ]}
    ];
get_routes(StaticPrefix, StaticDir, RestRoutes, undefined, Middles) ->
    StaticMatch = io_lib:format("/~s/[...]", StaticPrefix),
    [
        {'_', [
            {StaticMatch,   cowboy_static,  {dir, StaticDir}},
            {'_',           ehttp_handler,  #{routes => RestRoutes, middles => Middles}}
        ]}
    ];
get_routes(StaticPrefix, StaticDir, RestRoutes, RawRoutes, Middles) ->
    StaticMatch = io_lib:format("/~s/[...]", StaticPrefix),
    [
        {'_', RawRoutes ++ [
            {StaticMatch,   cowboy_static,  {dir, StaticDir}},
            {'_',           ehttp_handler,  #{routes => RestRoutes, middles => Middles}}
        ]}
    ].
